using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace AreaBuilder.Forms {
    public partial class frmObjects : Form {
        private readonly AreaHolder ah;
        private readonly int existingVNum = -1;

        public frmObjects(AreaHolder ah, int value) {
            InitializeComponent();

            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            changeColor(tabs, BackColor);
            // ReSharper restore DoNotCallOverridableMethodsInConstructor

            this.ah = ah;
            existingVNum = value;
        }

        private void frmObjects_Load(object sender, EventArgs e) {
            Funcs.fillCombo(cmbMaterials, "/types/materials/material");
            Funcs.fillCombo(cmbType, "/types/itemTypes/type/@name");
            Funcs.fillCombo(cmbObjPTrigger, "/types/objProgs/prog");
            Funcs.fillComboType(cmbMinSize, "/types/size/flag/@type", "/types/size/flag", "");
            Funcs.fillComboType(cmbMaxSize, "/types/size/flag/@type", "/types/size/flag", "");
            Funcs.fillComboType(cmbTrapDam, "/types/trigFlags/dam/@value", "/types/trigFlags/dam", "");
            Funcs.fillComboType(cmbFlagType, "/types/flagTypes/flag/@value", "/types/flagTypes/flag/name", "");
            Funcs.fillComboType(cmbFlagAttr, "/types/locFlags/loc/@value", "/types/locFlags/loc", "");
            Funcs.fillListType(lstExtra, "/types/extraFlags/flag/@value", "/types/extraFlags/flag", "");
            Funcs.fillListType(lstWear, "/types/wearFlags/flag/@value", "/types/wearFlags/flag", "");
            Funcs.fillListType(lstRestricted, "/types/restrictedFlags/flag/@value", "/types/restrictedFlags/flag", "");
            Funcs.fillListType(lstTriggers, "/types/trigFlags/trig/@value", "/types/trigFlags/trig", "");
            Funcs.fillListType(lstAvailApplies, "/types/locFlags/loc/@value", "/types/locFlags/loc", "");

            TextBox[] VTxt = { txtV0, txtV1, txtV2, txtV3, txtV4 };
            TrackBar[] VTrk = { trkV0, trkV1, trkV2, trkV3, trkV4 };
//            Label[] VLbl = { lblV0, lblV1, lblV2, lblV3, lblV4 };
//            Label[] VVal = { lblV0Val, lblV1Val, lblV2Val, lblV3Val, lblV4Val };
            ComboBox[] VCmb = { cmbV0, cmbV1, cmbV2, cmbV3, cmbV4 };

            cmbLevel.SelectedIndex = 0;
            trkTreasure.Value = 0;
            trkWeight.Value = 0;

            if (existingVNum >= 0) {
                Item i = (from Item it in ah.area.Items
                          where it.VNum == existingVNum
                          select it).Single();

                txtVNum.Text = i.VNum.ToString();
                txtKeywords.Text = i.Keywords;
                txtLong.Text = i.Description;
                txtShort.Text = i.Name;

                cmbType.SelectedIndex = Funcs.getComboIndex(cmbType, i.ItemType);
                cmbMaterials.SelectedIndex = Funcs.getComboIndex(cmbMaterials, i.Material);
                cmbMaxSize.SelectedIndex = Funcs.getComboIndex(cmbMaxSize, i.MaxSize.ToString());
                cmbMinSize.SelectedIndex = Funcs.getComboIndex(cmbMinSize, i.MinSize.ToString());
                cmbLevel.SelectedIndex = i.Level;

                Funcs.selectKeys(lstExtra, i.ExtraFlags);
                Funcs.selectKeys(lstWear, i.WearFlags);

                if (i.V5 != null)
                    Funcs.selectKeys(lstRestricted, i.V5);

                trkTreasure.Value = i.Cost;
                trkWeight.Value = i.Weight;

                var VType = new String[5];
                String[] ItemInfo = { i.V0.Replace("'", String.Empty), i.V1.Replace("'", String.Empty), i.V2.Replace("'", String.Empty), i.V3.Replace("'", String.Empty), i.V4.Replace("'", String.Empty) };

                for (int j = 0; j < 5; j++) {
                    if (cmbType.SelectedIndex < 0)
                        break;

                    VType[j] =
                        Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/@type",
                                                           cmbType.Items[cmbType.SelectedIndex], j));

                    if (String.Compare(VType[j], "text", true) == 0)
                        VTxt[j].Text = ItemInfo[j];
                    else if (String.Compare(VType[j], "combo", true) == 0)
                        VCmb[j].SelectedIndex = Funcs.getComboIndex(VCmb[j], ItemInfo[j]);
                    else if (String.Compare(VType[j], "track", true) == 0) {
                        try {
                            VTrk[j].Value = Int32.Parse(ItemInfo[j]);
                        } catch (Exception) {
                            VTrk[j].Value = VTrk[j].Minimum;
                        }
                    } else if (String.Compare(VType[j], "list", true) == 0)
                        Funcs.selectKeys(lstV4, ItemInfo[j]);
                }

                if (i.TrapLevel != null) {
                    trkTrapLvl.Value = Int32.Parse(i.TrapLevel);
                    cmbTrapDam.SelectedIndex = Funcs.getComboIndex(cmbTrapDam, i.TrapDamage);
                    Funcs.selectKeys(lstTriggers, i.TrapTrigger);
                    trkTrapCharges.Value = Int32.Parse(i.TrapCharges);
                    chkTrap.Checked = true;
                }

                if (i.Flags != null && i.Flags.Count > 0) {
                    for (int j = 0; j < i.Flags.Count; j++) {
                        var ifl = (ItemFlag)i.Flags[j];
                        chkFlag.Checked = true;
                        cmbFlagAttr.SelectedIndex = Funcs.getComboIndex(cmbFlagAttr, ifl.FlagLocation.ToString());
                        cmbFlagType.SelectedIndex = Funcs.getComboIndex(cmbFlagType, ifl.FlagType);
                        Funcs.selectKeys(lstFlagTarget, ifl.FlagBits);
                        trkFlagAttr.Value = ifl.FlagValue;
                    }
                }
                lstApplies.Items.Clear();

                if (i.Affects != null && i.Affects.Count > 0)
                    for (int j = 0; j < i.Affects.Count; j++)
                        addApply((ItemAffect)i.Affects[j]);

                if (!String.IsNullOrEmpty(i.ExtraDesc)) {
                    //i.ExtraDesc != null && !i.ExtraDesc.Equals("")) {
                    txtExtraDesc.Text = i.ExtraDesc.Replace("\n", Environment.NewLine);
                    txtExtraKeyword.Text = i.ExtraKeys;
                }

                lstObjprogs.Items.Clear();

                if (i.Triggers != null && i.Triggers.Count > 0) {
                    for (int j = 0; j < i.Triggers.Count; j++) {
                        var it = (ItemTrigger)i.Triggers[j];
                        it.TriggerSpell = Regex.Replace(it.TriggerSpell, @"~{2,}", "");

                        lstObjprogs.Items.Add(
                            String.Format("{0}                                       / {1}% / {2}ch / {3}",
                                          it.TriggerType, it.TriggerChance, it.TriggerCount, it.TriggerSpell));
                    }
                }

                btnClone.Enabled = true;
            } else {
                if (getNextVnum() < 0) {
                    MessageBox.Show("VNum Range was incremented by 100.", "Hrm...", MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);

                    ah.area.MaxVnum += 100;
                }

                txtVNum.Text = getNextVnum().ToString();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e) {
            Dispose();
        }

        private void btnOK_Click(object sender, EventArgs e) {
            SaveItem();

            Dispose();
        }

        private Item SaveItem() {
            TextBox[] VTxt = { txtV0, txtV1, txtV2, txtV3, txtV4 };
            TrackBar[] VTrk = { trkV0, trkV1, trkV2, trkV3, trkV4 };
            ComboBox[] VCmb = { cmbV0, cmbV1, cmbV2, cmbV3, cmbV4 };

            var VType = new String[5];

            Item i = existingVNum >= 0 ? (from Item item in ah.area.Items
                                          where item.VNum == existingVNum
                                          select item).Single() : new Item();

            i.VNum = Int32.Parse(txtVNum.Text);
            i.Keywords = txtKeywords.Text;
            i.Name = txtShort.Text;
            i.Description = txtLong.Text;
            i.Material = cmbMaterials.Items[cmbMaterials.SelectedIndex].ToString();
            i.ItemType = cmbType.Items[cmbType.SelectedIndex].ToString();
            i.ExtraFlags = Funcs.getFlags(lstExtra);

            if (!Funcs.getFlags(lstRestricted).Equals("0") && i.ExtraFlags.IndexOf("J") < 0) {
                i.ExtraFlags += "J";
            }

            i.WearFlags = Funcs.getFlags(lstWear);
            i.Level = cmbLevel.SelectedIndex;
            i.Weight = trkWeight.Value;
            i.MinSize = Int32.Parse(Funcs.getComboFlag(cmbMinSize));
            i.MaxSize = Int32.Parse(Funcs.getComboFlag(cmbMaxSize));
            i.Cost = trkTreasure.Value;

            for (int o = 0; o < 5; o++) {
                VType[o] =
                    Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/@type",
                                                       cmbType.Items[cmbType.SelectedIndex], o));

                switch (VType[o].ToLower()) {
                    case "text":
                        setV(o, i, VTxt[o].Text);
                        break;

                    case "combo":
                        if (VCmb[o].SelectedIndex >= 0) {
                            setV(o, i, Funcs.getComboFlag(VCmb[o])); //.Items[VCmb[o].SelectedIndex].ToString());
                        }
                        break;

                    case "track":
                        setV(o, i, VTrk[o].Value.ToString());
                        break;

                    case "list":
                        setV(o, i, Funcs.getFlags(lstV4));
                        break;

                    default:
                        MessageBox.Show("Stop messing with my types.xml!");
                        break;
                }
            }

            i.V5 = Funcs.getFlags(lstRestricted);

            if (chkTrap.Checked) {
                i.TrapCharges = trkTrapCharges.Value.ToString();
                i.TrapDamage = Funcs.getComboFlag(cmbTrapDam);
                i.TrapTrigger = Funcs.getFlags(lstTriggers);
                i.TrapLevel = trkTrapLvl.Value.ToString();
            }

            i.Affects.Clear();

            var re = new Regex(@"(?<val>[\-\+]?\d+) to .* \((?<loc>.+)\)$");
            for (int o = 0; o < lstApplies.Items.Count; o++) {
                Match m = re.Match(lstApplies.Items[o].ToString());
                var ia = new ItemAffect {
                    AffectType = Int32.Parse(m.Groups["loc"].ToString()),
                    AffectValue = Int32.Parse(m.Groups["val"].ToString())
                };

                i.Affects.Add(ia);
            }

            if (chkFlag.Checked) {
                i.Flags.Clear();
                var ifl = new ItemFlag {
                    FlagLocation = Int32.Parse(Funcs.getComboFlag(cmbFlagAttr)),
                    FlagType = Funcs.getComboFlag(cmbFlagType),
                    FlagBits = Funcs.getKeys(lstFlagTarget),
                    FlagValue = trkFlagAttr.Value
                }; // separate?

                i.Flags.Add(ifl);
            }

            var ree = new Regex(@"^(?<type>\w+)\s+/ (?<chance>\d+)% / (?<charges>\d+)ch / (?<arg>.+)$");

            i.Triggers.Clear();

            for (int j = 0; j < lstObjprogs.Items.Count; j++) {
                Match m = ree.Match(lstObjprogs.Items[j].ToString());

                if (m.Success) {
                    string arg = Regex.Replace(m.Groups["arg"].Value, @"~", "");

                    var it = new ItemTrigger {
                        TriggerChance = Int32.Parse(m.Groups["chance"].Value),
                        TriggerCount = Int32.Parse(m.Groups["charges"].Value),
                        TriggerSpell = arg,
                        TriggerType = m.Groups["type"].Value
                    };

                    i.Triggers.Add(it);
                }
            }

            i.ExtraDesc = txtExtraDesc.Text;
            i.ExtraKeys = txtExtraKeyword.Text;

            if (existingVNum < 0)
                ah.area.Items.Add(i);

            return i;
        }

        private void btnDel_Click(object sender, EventArgs e) {
            if (lstApplies.SelectedIndex >= 0) {
                lstApplies.Items.RemoveAt(lstApplies.SelectedIndex);

                updateAvailable();
            } else
                MessageBox.Show("You need to select an item apply to delete!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
        }

        private void btnAdd_Click(object sender, EventArgs e) {
            if (lstAvailApplies.SelectedIndex >= 0) {
                var ia = new ItemAffect {
                    AffectValue = trkApplyVal.Value,
                    AffectType = Int32.Parse(Funcs.getFlags(lstAvailApplies))
                };

                trkApplyVal.Value = 0;

                addApply(ia);
                updateAvailable();
            } else
                MessageBox.Show("You need to select an item apply to add!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
        }

        private void btnObjPAdd_Click(object sender, EventArgs e) {
            if (cmbObjPTrigger.SelectedIndex >= 0 && !String.IsNullOrEmpty(txtObjPArg.Text)) {
                lstObjprogs.Items.Add(String.Format("{0}                                       / {1}% / {2}ch / {3}",
                                                    cmbObjPTrigger.Items[cmbObjPTrigger.SelectedIndex],
                                                    trkObjPChance.Value, trkObjPCharges.Value, txtObjPArg.Text));
                trkObjPCharges.Value = 0;
                trkObjPChance.Value = 100;
            } else
                MessageBox.Show("Please use all fields!", "Whoops!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        private void btnObjPDel_Click(object sender, EventArgs e) {
            if (lstObjprogs.SelectedIndex >= 0) {
                lstObjprogs.Items.RemoveAt(lstObjprogs.SelectedIndex);
            } else
                MessageBox.Show("You need to select an objprog to delete!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
        }

        private void cmbType_SelectedIndexChanged(object sender, EventArgs e) {
            if (cmbType.SelectedIndex < 0)
                return;

            Label[] VLbl = { lblV0, lblV1, lblV2, lblV3, lblV4 };
            TextBox[] VTxt = { txtV0, txtV1, txtV2, txtV3, txtV4 };
            TrackBar[] VTrk = { trkV0, trkV1, trkV2, trkV3, trkV4 };
            Label[] VVal = { lblV0Val, lblV1Val, lblV2Val, lblV3Val, lblV4Val };
            ComboBox[] VCmb = { cmbV0, cmbV1, cmbV2, cmbV3, cmbV4 };

            var VEnabled = new Boolean[5];
            var VType = new String[5];
            var VName = new String[5];

            for (int i = 0; i < 5; i++) {
                VType[i] =
                    Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/@type",
                                                       cmbType.Items[cmbType.SelectedIndex], i));
                VName[i] =
                    Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/@name",
                                                       cmbType.Items[cmbType.SelectedIndex], i));
                VEnabled[i] =
                    Boolean.Parse(
                        Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/@enabled",
                                                           cmbType.Items[cmbType.SelectedIndex], i)));

                if (!String.IsNullOrEmpty(VName[i]))
                    VLbl[i].Text = String.Format("{0}:", VName[i]);

                VLbl[i].Enabled = VEnabled[i];

                VTxt[i].Visible = false;
                VTxt[i].Text = "";
                VTrk[i].Visible = false;
                VTrk[i].Value = VTrk[i].Minimum;
                VVal[i].Visible = false;
                VCmb[i].Visible = false;
                lstV4.Visible = false;

                String fillWith;
                String fillType;

                switch (VType[i].ToLower()) {
                    case "text":
                        VTxt[i].Visible = true;
                        break;

                    case "combo":
                        VCmb[i].Visible = true;
                        fillWith =
                            Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/fillWith",
                                                               cmbType.Items[cmbType.SelectedIndex], i));
                        fillType =
                            Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/fillType",
                                                               cmbType.Items[cmbType.SelectedIndex], i));

                        if (fillType.Equals("keyvnums")) {
                            VCmb[i].Items.Clear();
                            for (int j = 0; j < ah.area.Items.Count; j++) {
                                var it = (Item)ah.area.Items[j];

                                if (it.ItemType.ToLower().Equals("key")) {
                                    VCmb[i].Items.Add(String.Format("#{0} - {1}", it.VNum, it.Name));
                                }
                            }
                        } else if (fillType.Equals("roomvnums")) {
                            VCmb[i].Items.Clear();
                            for (int j = 0; j < ah.area.Rooms.Count; j++) {
                                var r = (Room)ah.area.Rooms[j];

                                VCmb[i].Items.Add(String.Format("#{0} - {1}", r.VNum, r.Title));
                            }
                        } else if (!String.IsNullOrEmpty(fillType) && !String.IsNullOrEmpty(fillWith))
                            Funcs.fillComboType(VCmb[i], fillType, fillWith, "");
                        else
                            Funcs.fillCombo(VCmb[i], fillWith);

                        break;

                    case "track":
                        VTrk[i].Minimum =
                            Int32.Parse(
                                Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/min",
                                                                   cmbType.Items[cmbType.SelectedIndex], i)));
                        VTrk[i].Maximum =
                            Int32.Parse(
                                Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/max",
                                                                   cmbType.Items[cmbType.SelectedIndex], i)));
                        VTrk[i].Visible = true;
                        VVal[i].Visible = true;
                        break;

                    case "list":
                        // This was a pain...
                        fillWith =
                            Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/fillWith",
                                                               cmbType.Items[cmbType.SelectedIndex], i));
                        fillType =
                            Funcs.getXPathSingle(String.Format("/types/itemTypes/type[@name='{0}']/V{1}/fillType",
                                                               cmbType.Items[cmbType.SelectedIndex], i));

                        lstV4.Visible = true;
                        lstV4.BringToFront();
                        Funcs.fillListType(lstV4, fillType, fillWith, "");

                        break;

                    default:
                        MessageBox.Show("Stop messing with my types.xml!");
                        break;
                }

                VVal[i].BringToFront();
                VTrk[i].BringToFront();
                VTxt[i].BringToFront();
                VCmb[i].BringToFront();
            }
        }

        private void cmbFlagType_SelectedIndexChanged(object sender, EventArgs e) {
            String flag = Funcs.getComboFlag(cmbFlagType);
            String fillType = Funcs.getXPathSingle(String.Format("/types/flagTypes/flag[@value = '{0}']/fillType", flag));
            String fillWith = Funcs.getXPathSingle(String.Format("/types/flagTypes/flag[@value = '{0}']/fillWith", flag));

            Funcs.fillListType(lstFlagTarget, fillType, fillWith, "");
        }

        private void lstObjprogs_SelectedIndexChanged(object sender, EventArgs e) {
            if (lstObjprogs.SelectedIndex < 0)
                return;

            var re = new Regex(@"^(?<type>\w+)\s+/ (?<chance>\d+)% / (?<charges>\d+)ch / (?<arg>.+)$");
            Match m = re.Match(lstObjprogs.Items[lstObjprogs.SelectedIndex].ToString());

            if (m.Success) {
                trkObjPChance.Value = Int32.Parse(m.Groups["chance"].Value);
                trkObjPCharges.Value = Int32.Parse(m.Groups["charges"].Value);
                txtObjPArg.Text = m.Groups["arg"].Value;
                cmbObjPTrigger.SelectedIndex = Funcs.getComboIndex(cmbObjPTrigger, m.Groups["type"].Value);
            }
        }

        private void trkTreasure_ValueChanged(object sender, EventArgs e) {
            if (trkTreasure.Value > 100) {
                int gold = trkTreasure.Value / 100;
                lblCostVal.Text = String.Format("{0}g {1}s", gold, trkTreasure.Value - (gold * 100));
            } else
                lblCostVal.Text = String.Format("{0}s", trkTreasure.Value);
        }

        private void trkWeight_ValueChanged(object sender, EventArgs e) {
            double lbs = trkWeight.Value / 10.0;
            lblWeightVal.Text = String.Format("{0:F1}lbs", lbs);
        }

        private void trkV0_ValueChanged(object sender, EventArgs e) {
            lblV0Val.Text = trkV0.Value.ToString();
        }

        private void trkV1_ValueChanged(object sender, EventArgs e) {
            if (String.Compare(cmbType.Items[cmbType.SelectedIndex].ToString(), "weapon", true) == 0) {
                lblV1Val.Text = String.Format("{0} (Ave: {1})", trkV1.Value,
                                              (((trkV1.Value * trkV2.Value) + trkV1.Value) / 2));
                lblV2Val.Text = String.Format("{0} (Ave: {1})", trkV2.Value,
                                              (((trkV1.Value * trkV2.Value) + trkV1.Value) / 2));
            } else
                lblV1Val.Text = trkV1.Value.ToString();
        }

        private void trkV2_ValueChanged(object sender, EventArgs e) {
            if (String.Compare(cmbType.Items[cmbType.SelectedIndex].ToString(), "weapon", true) == 0) {
                lblV1Val.Text = String.Format("{0} (Ave: {1})", trkV1.Value,
                                              (((trkV1.Value * trkV2.Value) + trkV1.Value) / 2));
                lblV2Val.Text = String.Format("{0} (Ave: {1})", trkV2.Value,
                                              (((trkV1.Value * trkV2.Value) + trkV1.Value) / 2));
            } else
                lblV2Val.Text = trkV2.Value.ToString();
        }

        private void trkV3_ValueChanged(object sender, EventArgs e) {
            lblV3Val.Text = trkV3.Value.ToString();
        }

        private void trkV4_ValueChanged(object sender, EventArgs e) {
            lblV4Val.Text = trkV4.Value.ToString();
        }

        private void trkTrapLvl_ValueChanged(object sender, EventArgs e) {
            lblTrapLvlVal.Text = trkTrapLvl.Value.ToString();
        }

        private void trkTrapCharges_ValueChanged(object sender, EventArgs e) {
            lblTrapChargesVal.Text = trkTrapCharges.Value.ToString();
        }

        private void trkApplyVal_ValueChanged(object sender, EventArgs e) {
            lblApplyVal.Text = trkApplyVal.Value.ToString();
        }

        private void trkFlagAttr_ValueChanged(object sender, EventArgs e) {
            lblFlagAttrVal.Text = trkFlagAttr.Value.ToString();
        }

        private void trkObjPCharges_ValueChanged(object sender, EventArgs e) {
            lblObjPChargesVal.Text = trkObjPCharges.Value.ToString();
        }

        private void trkObjPChance_ValueChanged(object sender, EventArgs e) {
            lblObjPChanceVal.Text = String.Format("{0}%", trkObjPChance.Value);
        }

        private void chkFlag_CheckedChanged(object sender, EventArgs e) {
            if (chkFlag.Checked) {
                lblFlagAff.Enabled = true;
                lblFlagAttr.Enabled = true;
                lblFlagAttrVal.Enabled = true;
                lblFlagTarget.Enabled = true;
                lblFlagType.Enabled = true;
                cmbFlagAttr.Enabled = true;
                cmbFlagType.Enabled = true;
                lstFlagTarget.Enabled = true;
                trkFlagAttr.Enabled = true;
            } else {
                lblFlagAff.Enabled = false;
                lblFlagAttr.Enabled = false;
                lblFlagAttrVal.Enabled = false;
                lblFlagTarget.Enabled = false;
                lblFlagType.Enabled = false;
                cmbFlagAttr.Enabled = false;
                cmbFlagType.Enabled = false;
                lstFlagTarget.Enabled = false;
                trkFlagAttr.Enabled = false;
            }
        }

        private void chkTrap_CheckedChanged(object sender, EventArgs e) {
            if (chkTrap.Checked) {
                lblTrapLvl.Enabled = true;
                lblTrapCharges.Enabled = true;
                lblTrapDam.Enabled = true;
                lblTrapChargesVal.Enabled = true;
                lblTrapLvlVal.Enabled = true;
                lblTrapTrigger.Enabled = true;
                trkTrapLvl.Enabled = true;
                trkTrapCharges.Enabled = true;
                cmbTrapDam.Enabled = true;
                lstTriggers.Enabled = true;
            } else {
                lblTrapLvl.Enabled = false;
                lblTrapCharges.Enabled = false;
                lblTrapDam.Enabled = false;
                lblTrapChargesVal.Enabled = false;
                lblTrapLvlVal.Enabled = false;
                lblTrapTrigger.Enabled = false;
                trkTrapLvl.Enabled = false;
                trkTrapCharges.Enabled = false;
                cmbTrapDam.Enabled = false;
                lstTriggers.Enabled = false;
            }
        }

        private void updateAvailable() {
            var re = new Regex(@" \((?<val>.+)\)$");
            var sb = new StringBuilder("[");

            for (int i = 0; i < lstApplies.Items.Count; i++) {
                Match m = re.Match(lstApplies.Items[i].ToString());

                if (m.Success)
                    sb.Append(String.Format("@value != {0} and ", m.Groups["val"]));
            }

            String cond = Regex.Replace(sb.ToString(), @" and $", "]");

            if (cond.Equals("["))
                cond = "";

            Funcs.fillListType(lstAvailApplies, String.Format("/types/locFlags/loc{0}/@value", cond),
                               String.Format("/types/locFlags/loc{0}", cond), "");
        }

        private void addApply(ItemAffect ia) {
            lstApplies.Items.Add(String.Format("{1}{0} to {2} ({3})", ia.AffectValue, (ia.AffectValue > 0 ? "+" : ""),
                                               Funcs.getXPathSingle(String.Format("/types/locFlags/loc[@value='{0}']",
                                                                                  ia.AffectType)), ia.AffectType));

            updateAvailable();
        }

        private static void setV(int i, Item it, String val) {
            if (i == 0)
                it.V0 = val.Contains(" ") ? String.Format("'{0}'", val) : val;
            else if (i == 1)
                it.V1 = val.Contains(" ") ? String.Format("'{0}'", val) : val;
            else if (i == 2)
                it.V2 = val.Contains(" ") ? String.Format("'{0}'", val) : val;
            else if (i == 3)
                it.V3 = val.Contains(" ") ? String.Format("'{0}'", val) : val;
            else if (i == 4)
                it.V4 = val.Contains(" ") ? String.Format("'{0}'", val) : val;
        }

        private int getNextVnum() {
            int start = ah.area.MinVnum;
            int end = ah.area.MaxVnum;

            for (int i = start; i < end + 1; i++) {
                if (!validObjVnum(i))
                    return i;
            }

            return -1;
        }

        private bool validObjVnum(int vnum) {
            try {
#pragma warning disable 168
                Item item = (from Item i in ah.area.Items
                             where i.VNum == vnum
                             select i).Single();
#pragma warning restore 168

                return true;
            } catch (InvalidOperationException) { }

            return false;
        }

        private static void changeColor(TabControl control, Color color) {
            for (int i = 0; i < control.TabCount; i++)
                control.TabPages[i].BackColor = color;
        }

        private void btnPrev_Click(object sender, EventArgs e) {
            try {
                int currVnum = Int32.Parse(txtVNum.Text);
                IEnumerable<int> query = from Item i in ah.area.Items
                                         where i.VNum < currVnum
                                         orderby i.VNum descending
                                         select i.VNum;
                int newArray = query.First();

                Form newForm = new frmObjects(ah, newArray) { MdiParent = MdiParent };

                newForm.Location = new Point((MdiParent.Size.Width - newForm.Size.Width) / 2 + 40,
                                             (MdiParent.Size.Height - newForm.Size.Height) / 2 - 60);
                newForm.Show();

                btnOK_Click(null, null);
            } catch (InvalidOperationException) {
                MessageBox.Show("There are no more mobs to show!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }

        private void btnNext_Click(object sender, EventArgs e) {
            try {
                int currVnum = Int32.Parse(txtVNum.Text);
                IEnumerable<int> query = from Item i in ah.area.Items
                                         where i.VNum > currVnum
                                         orderby i.VNum ascending
                                         select i.VNum;
                int newArray = query.First();

                Form newForm = new frmObjects(ah, newArray) { MdiParent = MdiParent };

                newForm.Location = new Point((MdiParent.Size.Width - newForm.Size.Width) / 2 + 40,
                                             (MdiParent.Size.Height - newForm.Size.Height) / 2 - 60);
                newForm.Show();

                btnOK_Click(null, null);
            } catch (InvalidOperationException) {
                MessageBox.Show("There are no more mobs to show!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }

        private void btnClone_Click(object sender, EventArgs e) {
            Item i = SaveItem().Clone();
            i.VNum = getNextVnum();

            ah.area.Items.Add(i);

            MessageBox.Show("Item was sucessfully cloned!", "Yay!", MessageBoxButtons.OK, MessageBoxIcon.Information);

            Form frmNew = new frmObjects(ah, i.VNum) { MdiParent = MdiParent };

            frmNew.Location = new Point((MdiParent.Size.Width - frmNew.Size.Width) / 2 + 40,
                                        (MdiParent.Size.Height - frmNew.Size.Height) / 2 - 60);
            frmNew.Show();

            Dispose();
        }
    }
}